/*=============================================================================
#    The element-comm is a tentative program used to test our ideas.           
#                       Copyright (C)  bgao                                    
#
#     This program is free software; you can redistribute it and/or            
#      modify it under the terms of the GNU General Public License             
#     as published by the Free Software Foundation; either version 2           
#         of the License, or (at your option) any later version.               
#
#     This program is distributed in the hope that it will be useful,          
#    but WITHOUT ANY WARRANTY; without even the implied warranty of           
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the            
#             GNU General Public License for more details.                    
#
#    You should have received a copy of the GNU General Public License        
#     along with this program; if not, write to the Free Software             
#      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,             
#                       MA  02110-1301, USA.                                  
#==============================================================================
# $Id$ 
#
# $Author$ 
#
# $Revision$ 
#
# $Date$ 
#
# Description: 
#
=============================================================================*/
#include 	"wsn-rf.h"
#include	"rtos-wsn.h"

/*!initialize the radio chip
 *	@return 
 */
int8 rf_init(void)
{
	/* Enable VREG EN  */
	rf_on();
	rf_reset();
	return 0;
}

/*!reset the radio chip and set up the initial setting
  *
  */
int8 rf_reset(void)
{
	RF_RESET();
	/* Hardware Address decode enable */	
	/* init PANID  */
	rf_set_pan_id(0xFFFF);	
	/* init short addr */
	rf_set_short_addr(0x0000);
	/* init ieee addr */
	rf_set_ieee_addr(0x00000000);
	/* Turn on automatic packet acknowledgment. */
	RF_ENABLE_AUTOACK();
	/* clear pan_coord*/
	RF_SET_PAN_COORDINATOR(0);
	/* init tx power*/
	rf_set_tx_power(31);

	return 0;
}
/*!radio chip power on
  *
  */
int8 rf_on(void)
{
	RF_ON();
	return 0;
}
/*!radio chip power off
  *
  */

int8 rf_off(void)
{
	RF_OFF();
	return 0;
}
/*!radio chip osc on
  *
  */

int8 rf_osc_on(void)
{
	RF_OSC_ON();
	return 0;
}
/*!radio chip osc off
  *
  */

int8 rf_osc_off(void)
{
	RF_OSC_OFF();
	return 0;
}

uint8 rf_tx_on(void)
{
	RF_TX_ON();
	return 0;
}
bool rf_tx_cca_on(void)
{
	RF_TX_CCA_ON();
	if(RF_TX_IS_ACTIVE())
		return TRUE;
	else
		return FALSE;
	
}

int8 rf_write_tx_fifo(uint8 *buf, uint8 len)
{
	if(len > 128)
		return -EINVAL;
	
	wsn_EnterCritical();
	RF_WRITE_TX_FIFO(buf,1);
	if(RF_TX_UNDERFLOWED())
	{
		rf_flush_tx_fifo();
		wsn_LeaveCritical();
		return -EUNDERFLOW;
	}
	RF_WRITE_TX_FIFO(buf+1,len-1);
	wsn_LeaveCritical();
	return 0;
}

int8 rf_read_rx_fifo(uint8 *buf, uint8 len)
{
	RF_READ_RX_FIFO(buf, len);
	return 0;
}
int8 rf_flush_tx_fifo(void)
{
	RF_FLUSH_TX_FIFO();
	return 0;
}
int8 rf_flush_rx_fifo(void)
{
	RF_FLUSH_RX_FIFO();
	return 0;
}
uint16 rf_set_short_addr(uint16 short_addr)
{
	RF_SET_SHORT_ADDR((uint8 *)&short_addr);
	
	return rf_get_short_addr();
}
uint16 rf_get_short_addr(void)
{
	uint16 addr;
	RF_GET_SHORT_ADDR((uint8 *)&addr);
	return addr;
}
uint16 rf_set_pan_id(uint16 pan_id)
{
	
	RF_SET_PAN_ID((uint8 *)&pan_id);
	if(pan_id == 0xFFFF)
		RF_SET_BCN_ACCEPT_ALL();
	else
		RF_CLR_BCN_ACCEPT_ALL();

	return rf_get_pan_id();
}

uint16 rf_get_pan_id(void)
{
	uint16 pan_id;
	RF_GET_PAN_ID((uint8 *)&pan_id);
	return pan_id;
}

uint64 rf_set_ieee_addr(uint64 ieee_addr)
{
	RF_SET_IEEE_ADDR((uint8 *)&ieee_addr);
	return rf_get_ieee_addr();
}

uint64 rf_get_ieee_addr(void)
{
	uint64 ieee_addr;
	RF_GET_IEEE_ADDR((uint8 *)&ieee_addr);
	return ieee_addr;
}

int8 rf_rx_on(void)
{
	RF_ENABLE_FIFOP_INT();
	RF_RX_ON();
	RF_WAIT_RSSI_VALID();
	//RF_FLUSH_RX_FIFO();//??
	return 0;
}
int8 rf_rxtx_off(void)
{
	RF_WAIT_TX_END();
	RF_RXTX_OFF();
	RF_DISABLE_FIFOP_INT();
	return 0;
}

int8 rf_ed_scan(void)
{
 	int8 rssi;
  	int8 rssi2;
  	int8 rssi3;
  	RF_WAIT_RSSI_VALID() {
        //printf("cc2420_rssi: RSSI not valid.\n");
  	}

	/* read three values, this is a workaround for a chip bug */
	rssi  = RF_RSSI_VALUE();
	rssi2 = RF_RSSI_VALUE();
	rssi3 = RF_RSSI_VALUE();

	/* if the first two values are equal, use that value, if not, use the third value */
	if (rssi != rssi2)
	{
    	rssi = rssi3;
  	}
  	return (rssi+CC2420_RSSI_OFFSET);
}
/*!set a new channel.
  * note: this function will turnoff the Rx and Tx
  */
int8  rf_set_chnl(uint8 chnl)
{
	if(chnl>26 && chnl < 11)
		return -EINVAL;
	rf_rxtx_off();
	RF_SET_CHANNEL(chnl);
	rf_rx_on();
	return 0;
}

int8 rf_enable_addr_recg(void)
{
	RF_ENABLE_ADR_FILTER();
	return 0;
}
int8 rf_disable_addr_recg(void)
{
	RF_DISABLE_ADR_FILTER();
	return 0;
}

int8 rf_set_pan_coord(void)
{
	RF_SET_PAN_COORDINATOR(1);
	return 0;
}
int8 rf_clr_pan_coord(void)
{
	RF_SET_PAN_COORDINATOR(0);
	return 0;
}

int8 rf_tx_ack(void)
{
	RF_TX_ACK();
	return 0;
}

int8 rf_tx_ack_pend(void)
{
	RF_TX_ACK_PEND();
	return 0;
}

int8 rf_set_tx_power(uint8 pa_level)
{
	RF_SET_TX_POWER(pa_level);
	return 0;
}

int8 rf_get_rx_power(void)
{
	return RF_GET_TX_POWER();
}

int8 rf_set_rx_threshold(uint8 thr_value)
{
	RF_SET_RX_THRESHOLD(thr_value);
	return 0;
}

uint8 rf_get_rand(void)
{
	return RF_RANDOM_BYTE();
}
#if 0
#define WITHCCA		1
#define	NONCCA		0
int8 rf_send(const void *buf, uint8 len, uint8 mode)
{
	rf_set_tx_power(31);
	RF_WAIT_TX_END();
	if(rf_write_tx_fifo(buf,len) < 0)
		return -ERROR;
	if(mode == WITHCCA)
	{
		rf_rx_on();
		if(RF_CHANNEL_CLEAR())
		{	
			if( rf_tx_cca_on() == FALSE)
				return -EAGAIN;
		}else
			return -EAGAIN;
	}else
		rf_tx_on();
	/*TODO:use SFD to monitor sending process and to get timestamp*/
}

int8 rf_recieve_isr(void)
{
	

}
#endif
